package org.manager.generic.web;

import java.io.IOException;
import java.io.Writer;
import java.util.Map;

import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessorMatcher;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.PropertyEditorRegistry;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.view.json.JsonStringWriter;
import org.springframework.web.servlet.view.json.JsonWriterConfiguratorTemplateRegistry;
import org.springframework.web.servlet.view.json.writer.jsonlib.AllwaysMatchingValueProcessorMatcher;
import org.springframework.web.servlet.view.json.writer.jsonlib.JsonlibJsonWriterConfiguratorTemplate;
import org.springframework.web.servlet.view.json.writer.jsonlib.NullPropertyFilter;
import org.springframework.web.servlet.view.json.writer.jsonlib.PropertyEditorRegistryValueProcessor;

public class MoyanJsonlibJsonStringWriter implements JsonStringWriter {

	protected final Log logger = LogFactory.getLog(getClass());

	private boolean enableJsonConfigSupport;
	
	private boolean convertAllMapValues;
	
	private boolean keepNullProperties;
	
	private JsonlibJsonWriterConfiguratorTemplate configuratorTemplate;
	
	@SuppressWarnings("unchecked")
	public void convertAndWrite(Map model, JsonWriterConfiguratorTemplateRegistry configuratorTemplateRegistry, Writer writer, BindingResult br) throws IOException{
		
		JsonConfig jsonConfig = null;
		
		if(configuratorTemplate == null){
			configuratorTemplate = (JsonlibJsonWriterConfiguratorTemplate) configuratorTemplateRegistry.findConfiguratorTemplate(JsonlibJsonWriterConfiguratorTemplate.class.getName());
		}
		
		if(enableJsonConfigSupport && configuratorTemplate != null ){
			jsonConfig = (JsonConfig) configuratorTemplate.getConfigurator();
		}
		
		if(jsonConfig == null)
			jsonConfig = new JsonConfig();
		
		if(jsonConfig.getJsonPropertyFilter() == null && !keepNullProperties)
			jsonConfig.setJsonPropertyFilter( new NullPropertyFilter()); 
		
		
		if(jsonConfig.getJsonValueProcessorMatcher().getClass().equals(JsonValueProcessorMatcher.DEFAULT.getClass())){
			PropertyEditorRegistry per = null;
			String objektName = null;
			
			if(br != null){
				per = br.getPropertyEditorRegistry();
				objektName = br.getObjectName();
			}
			
			PropertyEditorRegistryValueProcessor valueProzessor = new PropertyEditorRegistryValueProcessor(per);
			valueProzessor.setConvertAllMapValues(convertAllMapValues);
			valueProzessor.setObjektName(objektName);
			
			jsonConfig.registerJsonValueProcessor( AllwaysMatchingValueProcessorMatcher.class, valueProzessor );
			jsonConfig.setJsonValueProcessorMatcher(new AllwaysMatchingValueProcessorMatcher());
			
			jsonConfig.addJsonEventListener(valueProzessor);
			jsonConfig.enableEventTriggering();
			
		}
		
		JSON json = JSONSerializer.toJSON(model, jsonConfig ); 
		if(logger.isDebugEnabled())
			logger.debug(json.toString());
		
		json.write(writer);
		writer.flush();
	}

	public boolean isEnableJsonConfigSupport() {
		return enableJsonConfigSupport;
	}

	public void setEnableJsonConfigSupport(boolean enableJsonConfigSupport) {
		this.enableJsonConfigSupport = enableJsonConfigSupport;
	}

	public boolean isConvertAllMapValues() {
		return convertAllMapValues;
	}

	public void setConvertAllMapValues(boolean convertAllMapValues) {
		this.convertAllMapValues = convertAllMapValues;
	}

	public boolean isKeepNullProperties() {
		return keepNullProperties;
	}

	public void setKeepNullProperties(boolean keepNullProperties) {
		this.keepNullProperties = keepNullProperties;
	}
	
	public void setConfiguratorTemplate(
			JsonlibJsonWriterConfiguratorTemplate configuratorTemplate) {
		this.configuratorTemplate = configuratorTemplate;
	}
	

}
